﻿using System.Text.RegularExpressions;

namespace BepuPhysicsProcess
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var path = Environment.CurrentDirectory;
            path += @"\..\..\..\..\";
            Console.WriteLine(Path.GetFullPath(path));
            BEPUutilities(path);
            BepuPhysics(path);
            DemoRenderer(path);
            Demos(path);
            DemoContentLoader(path);
            DemoContentBuilder(path);
        }

        private static void DemoContentBuilder(string path)
        {
            //source: D:\bepuphysics2\DemoContentBuilder
            var sourceDirectory = path + @"..\..\bepuphysics2-master\DemoContentBuilder";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "DemoContentBuilder";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var textCode = File.ReadAllText(file);
                int index = 0;
            J: index = textCode.IndexOf("namespace", index);
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                if (index > 0)
                {
                    if (textCode[index - 1] == '/')
                    {
                        index += 10;
                        goto J;
                    }
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"using System.Numerics;", $"using BepuUtilities;");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics;", $"");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics.X86;", $"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                textCode = Regex.Replace(textCode, @"(?<!\d)(\d+(\.\d+)?|(\.\d+)|(\d+e[+-]?\d+)|(\.\d+e[+-]?\d+)|(\d+\.\d+e[+-]?\d+)|(\d+(\.\d+)?[eE][+-]?\d+))[fd](?!\d)", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        private static void DemoContentLoader(string path)
        {
            //source: D:\bepuphysics2\DemoContentLoader
            var sourceDirectory = path + @"..\..\bepuphysics2-master\DemoContentLoader";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "DemoContentLoader";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            //return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var textCode = File.ReadAllText(file);
                int index = 0;
            J: index = textCode.IndexOf("namespace", index);
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                if (index > 0)
                {
                    if (textCode[index - 1] == '/')
                    {
                        index += 10;
                        goto J;
                    }
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"using System.Numerics;", $"using BepuUtilities;");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics;", $"");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics.X86;", $"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                textCode = Regex.Replace(textCode, @"(?<!\d)(\d+(\.\d+)?|(\.\d+)|(\d+e[+-]?\d+)|(\.\d+e[+-]?\d+)|(\d+\.\d+e[+-]?\d+)|(\d+(\.\d+)?[eE][+-]?\d+))[fd](?!\d)", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        private static void Demos(string path)
        {
            //source: D:\bepuphysics2\BepuUtilities
            var sourceDirectory = path + @"..\..\bepuphysics2-master\Demos";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "Demos";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            //return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var textCode = File.ReadAllText(file);
                int index = 0;
            J: index = textCode.IndexOf("namespace", index);
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                if (index > 0)
                {
                    if (textCode[index - 1] == '/')
                    {
                        index += 10;
                        goto J;
                    }
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"using System.Numerics;", $"using BepuUtilities;");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics;", $"");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics.X86;", $"");
                textCode = textCode.Replace(@"sfloat maximumSlope = libm.PI * 0.25f", @"sfloat maximumSlope /*= libm.PI * 0.25f*/");
                textCode = textCode.Replace(@"sfloat linearDamping = .03f, sfloat angularDamping = .03f", @"sfloat linearDamping /*= .03f*/, sfloat angularDamping /*= .03f*/");
                textCode = textCode.Replace(@"MathHelper.Clamp(1 - LinearDamping, 0, 1)", @"MathHelper.Clamp(1 - LinearDamping, 0f, 1f)");
                textCode = textCode.Replace(@"MathHelper.Clamp(1 - AngularDamping, 0, 1)", @"MathHelper.Clamp(1 - AngularDamping, 0f, 1f)");
                textCode = textCode.Replace(@"sfloat maximumRecoveryVelocity = 2f, sfloat frictionCoefficient = 1f", @"sfloat maximumRecoveryVelocity /*= 2f*/, sfloat frictionCoefficient /*= 1f*/");
                textCode = textCode.Replace(@"sfloat cameraBackwardOffsetScale = 4", @"sfloat cameraBackwardOffsetScale /*= 4*/");
                textCode = textCode.Replace(@"const sfloat airControl", @"sfloat airControl");
                textCode = textCode.Replace(@"sfloat previewOffset = -1.2f", @"sfloat previewOffset /*= -1.2f*/");
                textCode = textCode.Replace(@"const sfloat ", @"sfloat ");
                textCode = textCode.Replace(@"private sfloat IntersectionEpsilon = 1e-4f;", @"private static sfloat IntersectionEpsilon = 1e-4f;");
                textCode = textCode.Replace(
                    @"new DemoNarrowPhaseCallbacks(new SpringSettings(30, 1)), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0))",
                    @"new DemoNarrowPhaseCallbacks(new SpringSettings(30, 1), 2f, 1f), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0), 2f, 1f)");
                textCode = textCode.Replace(@"location, new(default, ContinuousDetection.Passive), 0.01f", @"location, new(default, ContinuousDetection.Passive), (sfloat)0.01f");
                textCode = textCode.Replace(@"new TypedIndex() : vertexShapeIndex, 0.01f", @"new TypedIndex() : vertexShapeIndex, (sfloat)0.01f");
                textCode = textCode.Replace($"public DemoPoseIntegratorCallbacks(Vector3 gravity, sfloat linearDamping /*= .03f*/, sfloat angularDamping /*= .03f*/) : this()", $"public DemoPoseIntegratorCallbacks(Vector3 gravity) : this(gravity, 0.03f, 0.03f) {{ }}\r\n    public DemoPoseIntegratorCallbacks(Vector3 gravity, sfloat linearDamping /*= .03f*/, sfloat angularDamping /*= .03f*/) : this()");
                textCode = textCode.Replace(@"0.1f, 0.1f), -1", @"0.1f, 0.1f), -(sfloat)1");
                textCode = textCode.Replace(@"10.1f, 10.1f), -1", @"10.1f, 10.1f), -(sfloat)1");
                textCode = textCode.Replace(@"5, 5), -1));", @"5, 5), -(sfloat)1));");
                textCode = textCode.Replace(@"character.UpdateCameraPosition(camera);", @"character.UpdateCameraPosition(camera, 4);");
                textCode = textCode.Replace(@"var leftTargetSpeed = brakeLeft ? 0 : leftTargetSpeedFraction * Speed;", @"sfloat leftTargetSpeed = brakeLeft ? 0 : leftTargetSpeedFraction * Speed;");
                textCode = textCode.Replace(@"var rightTargetSpeed = brakeRight ? 0 : rightTargetSpeedFraction * Speed;", @"sfloat rightTargetSpeed = brakeRight ? 0 : rightTargetSpeedFraction * Speed;");
                textCode = textCode.Replace(@"var impulseScale = totalPenetrationImpulse > 0 ? frictionMagnitudeApproximation / totalPenetrationImpulse : 0;", @"sfloat impulseScale = totalPenetrationImpulse > 0 ? frictionMagnitudeApproximation / totalPenetrationImpulse : 0;");
                textCode = textCode.Replace(
                    $"public void Add(Vector3 position, string description, sfloat previewOffset /*= -1.2f*/, string previewText = \"Info...\")", 
                    $"public void Add(Vector3 position, string description)\r\n        => Add(position, description, -1.2f, \"Info...\");\r\n    public void Add(Vector3 position, string description, sfloat previewOffset /*= -(sfloat)1.2f*/, string previewText = \"Info...\")");
                textCode = textCode.Replace(
                    $"public DemoNarrowPhaseCallbacks(SpringSettings contactSpringiness, sfloat maximumRecoveryVelocity /*= 2f*/, sfloat frictionCoefficient /*= 1f*/)", 
                    $"public DemoNarrowPhaseCallbacks(SpringSettings contactSpringiness) : this(contactSpringiness, 2f, 1f) {{ }}\r\n    public DemoNarrowPhaseCallbacks(SpringSettings contactSpringiness, sfloat maximumRecoveryVelocity) : this(contactSpringiness, maximumRecoveryVelocity, 1f) {{ }}\r\n    public DemoNarrowPhaseCallbacks(SpringSettings contactSpringiness, sfloat maximumRecoveryVelocity /*= 2f*/, sfloat frictionCoefficient /*= 1f*/)");
                textCode = textCode.Replace(
                    @"var constraintActionProbability = originalConstraintCount > 0 ? 1 - (sfloat)simulation.Bodies.ActiveSet.Count / originalConstraintCount : 0;",
                    @"sfloat constraintActionProbability = originalConstraintCount > 0 ? 1 - (sfloat)simulation.Bodies.ActiveSet.Count / originalConstraintCount : 0;");
                textCode = textCode.Replace(
                    @"new DemoNarrowPhaseCallbacks(new SpringSettings(120, 1), maximumRecoveryVelocity: 1f),",
                    @"new DemoNarrowPhaseCallbacks(new SpringSettings(120, 1), maximumRecoveryVelocity: 1f, 1f),");
                textCode = textCode.Replace(@"RefitAndRefine(pool, i);", @"RefitAndRefine(pool, i, 1f);");
                textCode = textCode.Replace(@"RefitAndRefine(ref tree, pool, threadDispatcher, i);", @"RefitAndRefine(ref tree, pool, threadDispatcher, i, 1f);");
                textCode = textCode.Replace(@"new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0), angularDamping: 0.2f)", @"new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0), .03f, 0.2f)");
                textCode = textCode.Replace(@"new DemoNarrowPhaseCallbacks(new SpringSettings(30, 1), frictionCoefficient: 2)", @"new DemoNarrowPhaseCallbacks(new SpringSettings(30, 1), .03f, 2f)");
                textCode = textCode.Replace(@"    void Update(sfloat dt)", @"    void Update(float dt)");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                textCode = Regex.Replace(textCode, @"(?<!\d)(\d+(\.\d+)?|(\.\d+)|(\d+e[+-]?\d+)|(\.\d+e[+-]?\d+)|(\d+\.\d+e[+-]?\d+)|(\d+(\.\d+)?[eE][+-]?\d+))[fd](?!\d)", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        private static void DemoRenderer(string path)
        {
            //source: D:\bepuphysics2-master\BEPUutilities
            var sourceDirectory = path + @"..\..\bepuphysics2-master\DemoRenderer";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "DemoRenderer";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            //return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var textCode = File.ReadAllText(file);
                int index = 0;
            J: index = textCode.IndexOf("namespace", index);
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                if (index > 0)
                {
                    if (textCode[index - 1] == '/')
                    {
                        index += 10;
                        goto J;
                    }
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"using System.Numerics;", $"using BepuUtilities;");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics;", $"");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics.X86;", $"");
                textCode = textCode.Replace(@"sfloat maximumPitch = libm.PI * 0.499f", @"sfloat maximumPitch /*= libm.PI * 0.499f*/");
                textCode = textCode.Replace(@"sfloat gamma = 2.2f", @"sfloat gamma /*= 2.2f*/");
                textCode = textCode.Replace(@"libm.Clamp(value, 0, libm.PI / 2)", @"libm.Clamp(value, 0f, libm.PI / 2)");
                textCode = textCode.Replace(@"const sfloat sizeScale = 65535f / 4096f;", @"sfloat sizeScale = 65535f / 4096f;");
                textCode = textCode.Replace(@"new CompressToSwap(surface.Device, ShaderCache)", @"new CompressToSwap(surface.Device, ShaderCache, 2.2f)");
                textCode = textCode.Replace(@"var unpacked = (packed & ((1 << 15) - 1)) * (1f / ((1 << 15) - 1));", @"sfloat unpacked = (packed & ((1 << 15) - 1)) * (1f / ((1 << 15) - 1));");
                textCode = textCode.Replace($"public Camera(sfloat aspectRatio, sfloat fieldOfView, sfloat nearClip, sfloat farClip, sfloat maximumPitch /*= libm.PI * 0.499f*/)", $"public Camera(sfloat aspectRatio, sfloat fieldOfView, sfloat nearClip, sfloat farClip) : this(aspectRatio, fieldOfView, nearClip, farClip, libm.PI * 0.499f) {{ }}\r\n        public Camera(sfloat aspectRatio, sfloat fieldOfView, sfloat nearClip, sfloat farClip, sfloat maximumPitch /*= libm.PI * 0.499f*/)");

                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                //textCode = textCode.Replace(@"", @"");
                textCode = Regex.Replace(textCode, @"\d+\.\d+[fd]", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        private static void BepuPhysics(string path)
        {
            //source: D:\bepuphysics2-master\BEPUutilities
            var sourceDirectory = path + @"..\..\bepuphysics2-master\BepuPhysics";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "BepuPhysics";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            //return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var fileName = Path.GetFileName(file);
                if (Path.GetDirectoryName(file).EndsWith("Expansions"))
                    continue;
                var textCode = File.ReadAllText(file);
                var index = textCode.IndexOf("namespace");
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"using System.Numerics;", $"using BepuUtilities;");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics;", $"");
                textCode = textCode.Replace($"using System.Runtime.Intrinsics.X86;", $"");
                textCode = textCode.Replace(
                    $"if (Avx.IsSupported)\r\n                return (int)Vector128.ToScalar(Avx.PermuteVar(binIndicesForLeafContinuous.AsVector128(), permuteMask));\r\n            else if (Vector128.IsHardwareAccelerated)\r\n                return (int)Vector128.GetElement(binIndicesForLeafContinuous.AsVector128(), axisIndex);\r\n            else", 
                    $"");
                textCode = textCode.Replace($"sfloat leafToBinMultiplier = 1 / 16f", $"sfloat leafToBinMultiplier = default/*1 / 16f*/");
                textCode = textCode.Replace(
                    $"sfloat targetCandidateFraction = 0.005f, sfloat maximumCompressionFraction = 0.0005f",
                    $"sfloat targetCandidateFraction /*= 0.005f*/, sfloat maximumCompressionFraction /*= 0.0005f*/");
                textCode = textCode.Replace(
                    $"sfloat previousCapacityMultiplier = 1.25f", 
                    $"sfloat previousCapacityMultiplier = default /*1.25f*/");
                textCode = textCode.Replace($"sfloat minimumSweepTimestep = 1e-3f, sfloat sweepConvergenceThreshold = 1e-3f", $"sfloat minimumSweepTimestep /*= 1e-3f*/, sfloat sweepConvergenceThreshold /*= 1e-3f*/");
                textCode = textCode.Replace($"sfloat refineAggressivenessScale = 1", $"sfloat refineAggressivenessScale /*= 1*/");
                textCode = textCode.Replace(
                    $"const sfloat min = 1e-5f;\r\n                        const sfloat max = 3e-4f;\r\n                        const sfloat inverseSpan = 1f / (max - min);", 
                    $"sfloat min = 1e-5f;\r\n                        sfloat max = 3e-4f;\r\n                        sfloat inverseSpan = 1f / (max - min);");
                textCode = textCode.Replace($"RefitAndRefine(Pool, frameIndex);", $"RefitAndRefine(Pool, frameIndex, 1f);");
                textCode = textCode.Replace($"const sfloat ", $"sfloat ");
                textCode = textCode.Replace($"new BatchCompressor(simulation.Solver, simulation.Bodies);", $"new BatchCompressor(simulation.Solver, simulation.Bodies, 0.005f, 0.0005f);");
                textCode = textCode.Replace(
                    @"public static BodyDescription CreateDynamic(RigidPose pose, BodyVelocity velocity, BodyInertia inertia, CollidableDescription collidable, BodyActivityDescription activity)",
                    $"public static BodyDescription CreateDynamic(RigidPose pose, BodyVelocity velocity, BodyInertia inertia, CollidableDescription collidable, sfloat activity)\r\n            => CreateDynamic(pose, velocity, inertia, collidable, (BodyActivityDescription)activity);\r\n        public static BodyDescription CreateDynamic(RigidPose pose, BodyVelocity velocity, BodyInertia inertia, CollidableDescription collidable, BodyActivityDescription activity)");
                textCode = textCode.Replace(
                    $"public static BodyDescription CreateKinematic(RigidPose pose, BodyVelocity velocity, CollidableDescription collidable, BodyActivityDescription activity)", 
                    $"public static BodyDescription CreateKinematic(RigidPose pose, BodyVelocity velocity, CollidableDescription collidable, sfloat activity)\r\n            => CreateKinematic(pose, velocity, collidable, (BodyActivityDescription)activity);\r\n        public static BodyDescription CreateKinematic(RigidPose pose, BodyVelocity velocity, CollidableDescription collidable, BodyActivityDescription activity)");
                textCode = textCode.Replace(
                    $"public static BodyDescription CreateDynamic(RigidPose pose, BodyInertia inertia, CollidableDescription collidable, BodyActivityDescription activity)", 
                    $"public static BodyDescription CreateDynamic(RigidPose pose, BodyInertia inertia, CollidableDescription collidable, sfloat activity)\r\n            => CreateDynamic(pose, inertia, collidable, (BodyActivityDescription)activity);\r\n        public static BodyDescription CreateDynamic(RigidPose pose, BodyInertia inertia, CollidableDescription collidable, BodyActivityDescription activity)");
                textCode = textCode.Replace(
                    $"public static BodyDescription CreateKinematic(RigidPose pose, CollidableDescription collidable, BodyActivityDescription activity)", 
                    $"public static BodyDescription CreateKinematic(RigidPose pose, CollidableDescription collidable, sfloat activity)\r\n            => CreateKinematic(pose, collidable, (BodyActivityDescription)activity);\r\n        public static BodyDescription CreateKinematic(RigidPose pose, CollidableDescription collidable, BodyActivityDescription activity)");
                textCode = textCode.Replace($"Debug.Assert(libm.Abs(description.Pose.Orientation.Length() - 1)", $"//Debug.Assert(libm.Abs(description.Pose.Orientation.Length() - 1)");
                textCode = textCode.Replace($"Debug.Assert(libm.Abs(1 - description.Pose.Orientation.LengthSquared())", $"//Debug.Assert(libm.Abs(1 - description.Pose.Orientation.LengthSquared())");
                textCode = textCode.Replace($"Debug.Assert(libm.Abs(1 - description.Pose.Orientation.LengthSquared())", $"//Debug.Assert(libm.Abs(1 - description.Pose.Orientation.LengthSquared())");
                textCode = textCode.Replace($"Debug.Assert(libm.Abs(normal.LengthSquared() - 1)", $"//Debug.Assert(libm.Abs(normal.LengthSquared() - 1)");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                textCode = Regex.Replace(textCode, @"(?<!\d)(\d+(\.\d+)?|(\.\d+)|(\d+e[+-]?\d+)|(\.\d+e[+-]?\d+)|(\d+\.\d+e[+-]?\d+)|(\d+(\.\d+)?[eE][+-]?\d+))[fd](?!\d)", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        private static void BEPUutilities(string path)
        {
            //source: D:\bepuphysics2-master\BepuUtilities
            var sourceDirectory = path + @"..\..\bepuphysics2-master\BepuUtilities";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "BepuUtilities";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            //return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var fileName = Path.GetFileName(file);
                if (Path.GetDirectoryName(file).EndsWith("Expansions"))
                    continue;
                var textCode = File.ReadAllText(file);
                var index = textCode.IndexOf("namespace");
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", "sfloat");
                textCode = textCode.Replace("double", "sfloat");
                textCode = textCode.Replace("MathF", "libm");
                textCode = textCode.Replace(@"System.Math.", @"libm.");
                textCode = textCode.Replace("Math.", "libm.");
                textCode = textCode.Replace(@"public const sfloat", @"public static sfloat");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<sfloat>.Count == 8)\r\n            {{\r\n                return Avx.Reciprocal(v.AsVector256()).AsVector();\r\n            }}\r\n            else if (Sse.IsSupported && Vector<sfloat>.Count == 4)\r\n            {{\r\n                return Sse.Reciprocal(v.AsVector128()).AsVector();\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<sfloat>.Count == 8)\r\n            {{\r\n                return Avx.ReciprocalSqrt(v.AsVector256()).AsVector();\r\n            }}\r\n            else if (Sse.IsSupported && Vector<sfloat>.Count == 4)\r\n            {{\r\n                return Sse.ReciprocalSqrt(v.AsVector128()).AsVector();\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Vector128.IsHardwareAccelerated)\r\n            {{\r\n                Unsafe.SkipInit(out merged);\r\n                ref var resultMin = ref Unsafe.As<TA, Vector128<sfloat>>(ref merged);\r\n                ref var resultMax = ref Unsafe.Add(ref Unsafe.As<TA, Vector128<sfloat>>(ref merged), 1);\r\n                var min = Vector128.Min(\r\n                    Unsafe.As<TA, Vector128<sfloat>>(ref Unsafe.AsRef(in boundingBoxA)),\r\n                    Unsafe.As<TB, Vector128<sfloat>>(ref Unsafe.AsRef(in boundingBoxB)));\r\n                var max = Vector128.Max(\r\n                    Unsafe.Add(ref Unsafe.As<TA, Vector128<sfloat>>(ref Unsafe.AsRef(in boundingBoxA)), 1),\r\n                    Unsafe.Add(ref Unsafe.As<TB, Vector128<sfloat>>(ref Unsafe.AsRef(in boundingBoxB)), 1));\r\n                if (Sse41.IsSupported)\r\n                {{\r\n                    resultMin = Sse41.Blend(min, resultMin, 0b1000);\r\n                    resultMax = Sse41.Blend(max, resultMax, 0b1000);\r\n                }}\r\n                else\r\n                {{\r\n                    var mask = Vector128.Create(-1, -1, -1, 0).As<int, sfloat>();\r\n                    resultMin = Vector128.ConditionalSelect(mask, min, resultMin);\r\n                    resultMax = Vector128.ConditionalSelect(mask, max, resultMax);\r\n                }}\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<int>.Count == 8)\r\n            {{\r\n                var scalarMask = Avx.MoveMask(v.AsVector256().As<int, sfloat>());\r\n                return BitOperations.TrailingZeroCount(scalarMask);\r\n            }}\r\n            else if (Sse.IsSupported && Vector<int>.Count == 4)\r\n            {{\r\n                var scalarMask = Sse.MoveMask(v.AsVector128().As<int, sfloat>());\r\n                return BitOperations.TrailingZeroCount(scalarMask);\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<int>.Count == 8)\r\n            {{\r\n                var scalarMask = Avx.MoveMask(v.AsVector256().As<int, sfloat>());\r\n                return 32 - BitOperations.LeadingZeroCount((uint)scalarMask);\r\n            }}\r\n            else if (Sse.IsSupported && Vector<int>.Count == 4)\r\n            {{\r\n                var scalarMask = Sse.MoveMask(v.AsVector128().As<int, sfloat>());\r\n                return 32 - BitOperations.LeadingZeroCount((uint)scalarMask);\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<int>.Count == 8)\r\n            {{\r\n                return Avx.CompareGreaterThan(Vector256.Create((sfloat)countInBundle), Vector256.Create(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f)).AsInt32().AsVector();\r\n            }}\r\n            else if (Sse.IsSupported && Vector<int>.Count == 4)\r\n            {{\r\n                return Sse.CompareGreaterThan(Vector128.Create((sfloat)countInBundle), Vector128.Create(0f, 1f, 2f, 3f)).AsInt32().AsVector();\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"if (Avx.IsSupported && Vector<int>.Count == 8)\r\n            {{\r\n                return Avx.CompareLessThanOrEqual(Vector256.Create((sfloat)countInBundle), Vector256.Create(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f)).AsInt32().AsVector();\r\n            }}\r\n            else if (Sse.IsSupported && Vector<int>.Count == 4)\r\n            {{\r\n                return Sse.CompareLessThanOrEqual(Vector128.Create((sfloat)countInBundle), Vector128.Create(0f, 1f, 2f, 3f)).AsInt32().AsVector();\r\n            }}\r\n            else", $"");
                textCode = textCode.Replace($"MathHelper.Clamp(qw, -1, 1)", $"MathHelper.Clamp(qw, -1f, 1f)");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                textCode = Regex.Replace(textCode, @"(?<!\d)(\d+(\.\d+)?|(\.\d+)|(\d+e[+-]?\d+)|(\.\d+e[+-]?\d+)|(\d+\.\d+e[+-]?\d+)|(\d+(\.\d+)?[eE][+-]?\d+))[fd](?!\d)", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                File.WriteAllText(file, textCode);
            }
        }

        static void CopyDirectory(string sourceDir, string destDir)
        {
            // 创建目标文件夹
            if (!Directory.Exists(destDir))
                Directory.CreateDirectory(destDir);

            // 复制所有文件
            foreach (string file in Directory.GetFiles(sourceDir, "*.cs"))
            {
                string destFile = Path.Combine(destDir, Path.GetFileName(file));
                File.Copy(file, destFile, true); // true 表示如果目标文件已存在，则覆盖
            }

            // 递归复制所有子文件夹
            foreach (string directory in Directory.GetDirectories(sourceDir))
            {
                var directoryInfo = new DirectoryInfo(directory);
                if (directoryInfo.Name == "obj" | directoryInfo.Name == "bin")
                    continue;
                string destSubDir = Path.Combine(destDir, Path.GetFileName(directory));
                CopyDirectory(directory, destSubDir);
            }
        }
    }
}
